<?php

require '../utiles.php';
require 'lib/Neurona.php';


//Suponemos que es posible definir una neurona RBF n dimensional.
class  NeuronaRBF {
	private $media;
	private $desvio;
	private $dimensiones;
	
	//$maximos es un array de los rangos maximos y minimos de cada dimension.
	// $maximos[0] = 10; $minimos[0] = -10; => X estará entre -10 y 10...
	// historia_media define cuantos instantes anteriores tiene la media
	function __construct ($maximos, $minimos) {
		//Inicializamos al azar la media y el desvio
		$this -> dimensiones = count($maximos);
		if ($this -> dimensiones != count($minimos))
			die('Las dimensiones de rangos máximos y mínimos no coincide');
		
		for ($i = 0; $i < $this -> dimensiones; $i++) {
			$this->media[] = mt_randf($minimos[$i], $maximos[$i]);
		}
		//echo "Media Neurona<br>";
		//printe($this->media);
	}
	
	function get_centroide() {
		return $this->media;
	}
	
	function redefinir_centroide($centro) {
		if (count($centro) != $this->dimensiones)
			die('Las dimensiones del nuevo centro no coinciden con las actuales');
		
		$this->media = $centro;
	}

}; //Fin de la clase NeuronaRBF


//Pseudocodigo kmeans

$nodos = 5;
$minimos = array(-1, -1);
$maximos = array(1  , 1);
$dimension= count($maximos);
$ultimas_asignaciones = array();

$data = array(
		array(-1,-1,0),
		array(-1,1,1),
		array(1,-1,1),
		array(1,1,0),
		array(0,0,0),
);
printe($data);
$neuronas = array();

for ($i = 0; $i < $nodos; $i++) {
	$neuronas[] = new NeuronaRBF($maximos, $minimos);
}

$n = count($data);


while (true) {
	$punto_grupo = array(); //Asignacion de un punto a un grupo
	//Recorremos cada punto
	for ($i = 0; $i < $n ; $i++) {
		//etiquetamos a cada punto al centroide mas cercano
		$cercano = $distancia = null;
		foreach($neuronas as $id_neurona => $neurona) {
			$dist = distancia_euclidea( get_n_izq($data[$i],$dimension) , $neurona->get_centroide());
			if ($cercano == null || $dist < $distancia) {
				$cercano = $i;
				$distancia = $dist;
				//if (!isset($punto_grupo[$i])) //Esto es para que por las dudas no haya 1 punto en distintos grupos
				$punto_grupo[$i] = $id_neurona;
			}
		}
	}
	if ($ultimas_asignaciones == $punto_grupo)
		break;
	else
		$ultimas_asignaciones = $punto_grupo;
	echo "Las asignaciones punto_grupo";
	printe($punto_grupo);
	//redefinimos los centroides

	//Aca almacenaré un vector para cada dimension 
	$vector_cero = array();
	for ($i = 0 ; $i < $dimension; $i++) $vector_cero[$i] = 0;
	//Cantidad de puntos por grupo : Para poder sacar el promedio.
	$puntos_por_grupo = array();
	for ($i = 0 ; $i < $nodos; $i++) $puntos_por_grupo[$i] = 0; 

	$nuevos_centroides = array();

	foreach ($punto_grupo as $id_punto => $id_neurona) {
		if (!isset($nuevos_centroides[$id_neurona]))
			$nuevos_centroides[$id_neurona] = $vector_cero;
		$nuevos_centroides[$id_neurona] = suma_vectores($nuevos_centroides[$id_neurona] , get_n_izq($data[$id_punto], $dimension) );
		$puntos_por_grupo[$id_neurona]++;
	}

	foreach ($neuronas as $id_neurona => $neurona) {
		if ($puntos_por_grupo[$id_neurona] < 1) {
			echo "<span style='font-size: 20px; color: orange; background: blue'>Hay un grupo vacio</span><br /><br />"; die;
			//echo '<script type="text/javascript">location.reload(true)</script>';
		}
		$neurona->redefinir_centroide(dividir_vector($nuevos_centroides[$id_neurona],$puntos_por_grupo[$id_neurona]));
		//echo "Nuevo centroide para la neurona $id_neurona:";
		//printe($neurona->get_centroide());
	}
}


$n_salidas = count($data[0]) - $dimension;

$neuronas_salida = array();
$epocas = 500;

//Calculamos los patrones
$input = array();
$output = array();
foreach ($data as $id_punto => $datilla) {
	$tempy = array_pad ( array() , $nodos , 0 ) ;
	$tempy[$punto_grupo[$id_punto]] = 1;
	
	$input[] = $tempy;
	$output[] = get_n_der($datilla, $n_salidas);
}

for ( $i=0 ; $i<$n_salidas; $i++ ){
	$neuronas_salida[$i] = new Neurona( array('cantEntradas' => $nodos,'tasaAprendizaje' => 0.09) );
	$neuronas_salida[$i]->entrenar_N($input, $output, $epocas, 0.1);
}




/* TESTIAMOS */

$ultimas_asignaciones = array();

$data = array(
		array(-1,-1,0),
		array(-1,1,1),
		array(1,-1,1),
		array(1,1,0),
		array(0,0,0)
);

for ($i = 0; $i < $n ; $i++) {
	//etiquetamos a cada punto al centroide mas cercano
	$cercano = $distancia = null;
	foreach($neuronas as $id_neurona => $neurona) {
		$dist = distancia_euclidea( get_n_izq($data[$i],$dimension) , $neurona->get_centroide());
		if ($cercano == null || $dist < $distancia) {
			$cercano = $i;
			$distancia = $dist;
			//if (!isset($punto_grupo[$i])) //Esto es para que por las dudas no haya 1 punto en distintos grupos
			$punto_grupo[$i] = $id_neurona;
		}
	}
}


//Calculamos los patrones DE TESTING
$input = array();
$output = array();
foreach ($data as $id_punto => $datilla) {
	$tempy = array_pad ( array() , $nodos , 0 ) ;
	$tempy[$punto_grupo[$id_punto]] = 1;
	
	$input[] = $tempy;
	$output[] = get_n_der($datilla, $n_salidas);
}

for ( $i=0 ; $i<$n_salidas; $i++ ){
	$neuronas_salida[$i]->prueba($input, $output);
}


